/**
 * Copyright (C) 2010 Cloudfarming <info@cloudfarming.nl>
 *
 * Licensed under the Eclipse Public License - v 1.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.eclipse.org/legal/epl-v10.html
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package nl.cloudfarming.client.sensor;

import java.util.List;
import java.util.Set;
import javax.persistence.NoResultException;
import javax.persistence.Query;
import javax.swing.ActionMap;
import javax.swing.text.DefaultEditorKit;
import nl.cloudfarming.client.model.CommonModelService;
import nl.cloudfarming.client.model.DataProvider;
import nl.cloudfarming.client.model.SensorData;
import nl.cloudfarming.client.model.SensorDataFile;
import nl.cloudfarming.client.model.SensorMetadata;
import nl.cloudfarming.client.model.SensorRun;
import nl.cloudfarming.client.sensor.explorer.SensorRootNode;
import org.openide.explorer.ExplorerManager;
import org.openide.explorer.ExplorerUtils;
import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider;
import org.openide.util.lookup.ServiceProviders;

/**
 *
 * @author Timon Veenstra
 */
@ServiceProviders(value = {
    @ServiceProvider(service = DataProvider.class),
    @ServiceProvider(service = SensorService.class)
})
public class SensorService extends CommonModelService{

    @Override
    protected String getModuleName() {
        return SensorModule.MODULE_NAME;
    }

    

    public void newSensorDataFile(SensorDataFile sensorDataFile){
        startTransaction();
        getEntityManager().persist(sensorDataFile);
        if (sensorDataFile.getMetadata() != null){
            getEntityManager().persist(sensorDataFile.getMetadata());
        }
        for (SensorData sd:(Set<SensorData>)sensorDataFile.getSensorData()){
            getEntityManager().persist(sd);
        }
        commit();
    }

    public void newSensorMetaData(SensorMetadata sensorMetadata){
        persistInTransaction(sensorMetadata);
    }

    public List<SensorData> findDataForRun(SensorRun sensorRun){
         Query q = getEntityManager().createNamedQuery(SensorData.Q_FIND_DATA_FOR_RUN);
         q.setParameter(SensorData.P_FIND_DATA_FOR_RUN, sensorRun);
         return q.getResultList();
    }

    public List<SensorRun> findSensorRuns(){
         Query q = getEntityManager().createNamedQuery(SensorRun.Q_FIND_ALL_RUNS);
         return q.getResultList();
    }
     
    // Moved from CommonModelService
    public List<SensorData> findUnlinkedSensorData() {
        startTransaction();

        Query query = getEntityManager().createQuery("select s from SensorData s where s.sensorRun is null");
        List<SensorData> result = query.getResultList();

        return result;
    }

    // Moved from CommonModelService
    public List<SensorData> findlinkedSensorData() {
        startTransaction();

        Query query = getEntityManager().createQuery("select s from SensorData s where s.sensorRun is not null");
        List<SensorData> result = query.getResultList();

        return result;
    }

    // Moved from CommonModelService
    public SensorMetadata findMetaDataByMetadata(String dateFormat, int sensorHeight, int numberOfSensors, String sensorSpread, String sensorType, String spectralChannels) {
        startTransaction();
        Query query = getEntityManager().createQuery(
                "select c from SensorMetadata c "
                + "where c.dateFormat = :dateFormat "
                + "and c.sensorHeight = :sensorHeight "
                + "and c.numberOfSensors = :numberOfSensors "
                + "and c.sensorSpread = :sensorSpread "
                + "and c.sensorType = :sensorType "
                + "and c.spectralChannels = :spectralChannels");
        query.setParameter("dateFormat", dateFormat);
        query.setParameter("sensorHeight", sensorHeight);
        query.setParameter("numberOfSensors", numberOfSensors);
        query.setParameter("sensorSpread", sensorSpread);
        query.setParameter("sensorType", sensorType);
        query.setParameter("spectralChannels", spectralChannels);
        try {
            return (SensorMetadata) query.getSingleResult();
        } catch (NoResultException ner) {
            return null;
        }
    }

    // Moved from CommonModelService
    public SensorDataFile findFileByNameAndChecksum(String fileName, String checksum) {
        startTransaction();
        Query query = getEntityManager().createQuery(
                "select c from SensorDataFile c "
                + "where c.fileName = :fileName "
                + "and c.checksum = :checksum");
        query.setParameter("fileName", fileName);
        query.setParameter("checksum", checksum);
        try {
            return (SensorDataFile) query.getSingleResult();
        } catch (NoResultException ner) {
            return null;
        }
    }

    // Moved from CommonModelService
    public List<SensorDataFile> findAllSensorDataFiles() {
        startTransaction();
        Query query = this.getEntityManager().createQuery("select c from SensorDataFile c");
        return query.getResultList();
    }

    // Moved from CommonModelService
    public List<SensorMetadata> findAllSensorMetadata() {
        startTransaction();
        Query query = this.getEntityManager().createQuery("select c from SensorMetadata c");
        return query.getResultList();
    }

    // Moved from CommonModelService
    public SensorMetadata findMetadataById(long id) {
        startTransaction();
        return getEntityManager().find(SensorMetadata.class, id);
    }

    // Moved from CommonModelService
    public SensorDataFile findDataFileById(long id) {
        startTransaction();
        return getEntityManager().find(SensorDataFile.class, id);
    }

    @Override
    protected void initExplorer() {
        //FIXME add explorer creattion
        ExplorerManager manager = new ExplorerManager();
        //todo, setup nodes for sensor data
        manager.setRootContext(new SensorRootNode());
        manager.getRootContext().setDisplayName(NbBundle.getMessage(this.getClass(), "sensor_explorer.rootnode"));

        ActionMap map = new ActionMap();
        map.put(DefaultEditorKit.copyAction, ExplorerUtils.actionCopy(manager));
        map.put(DefaultEditorKit.cutAction, ExplorerUtils.actionCut(manager));
        map.put(DefaultEditorKit.pasteAction, ExplorerUtils.actionPaste(manager));
        map.put("delete", ExplorerUtils.actionDelete(manager, true)); // or false

        setExplorerManager(manager, map);
    }

}
